/*
 * Copyright (c) 2010, okazoh_tk. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "alkes/tree/TransformVisual.h"

namespace alkes {


TransformVisual::TransformVisual()
: scale_(Vector2D::ONE)
, degrees_(0)
, origin_(Vector2D::HALF)
{
}

void TransformVisual::setScale(const Vector2D& scale)
{
    setProperty(scale_, scale);
}

void TransformVisual::setRotate(float degrees)
{
    setProperty(degrees_, degrees);
}

void TransformVisual::setOrigin(const Vector2D& origin)
{
    setProperty(origin_, origin);
}

const Vector2D& TransformVisual::getScale() const
{
    return scale_;
}

float TransformVisual::getRotate() const
{
    return degrees_;
}

const Vector2D& TransformVisual::getOrigin() const
{
    return origin_;
}

void TransformVisual::onRender(GraphicsContext& gc)
{
    if (!needRender())
        return ; // do nothing

    IRenderTarget2D* target = gc.getRenderTarget2D();

    bool enable_transform = needTransform(target);

    if (enable_transform)
    {
        target->pushMatrix();

        setTranslate(target, getDest());

        setScale(target, scale_);
        setRotate(target, getSize(), origin_, degrees_);
    }

    onRenderObject(gc);

    if (enable_transform)
    {
        target->popMatrix();
    }
}

bool TransformVisual::needRender() const
{
    return true;
}

bool TransformVisual::needTransform(IRenderTarget2D* target) const
{
    return needTranslate(target)
        || degrees_ != 0
        || scale_ != Vector2D::ONE;
}

bool TransformVisual::needTranslate(IRenderTarget2D* /*target*/) const
{
    return !isNullDest();
}

void TransformVisual::setTranslate(IRenderTarget2D* target, const Point2D& dest) const
{
    target->translate(dest.x, dest.y);
}

void TransformVisual::setRotate(IRenderTarget2D* target, const RectSize& size, const Vector2D& origin, float degrees) const
{
    if (degrees == 0)
        return ;

    target->rotate(degrees, UVector2D(size.width * origin.x, size.height * origin.y));
}

void TransformVisual::setScale(IRenderTarget2D* target, const Vector2D& scale) const
{
    if (scale == Vector2D::ONE)
        return ;

    target->scale(scale.x, scale.y);
}

}

